package nl.tudelft.jpacman.level;


import nl.tudelft.jpacman.PacmanConfigurationException;
import nl.tudelft.jpacman.board.BoardFactory;
import nl.tudelft.jpacman.board.Square;
import nl.tudelft.jpacman.npc.Ghost;
import nl.tudelft.jpacman.npc.ghost.GhostFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

public class MapParserTest {
    private MapParser mapParser;
    private LevelFactory levelFactory;
    private BoardFactory boardFactory;
    private GhostFactory ghostFactory;

    @BeforeEach
    public void setUp() {
        levelFactory = mock(LevelFactory.class);
        boardFactory = mock(BoardFactory.class);
        ghostFactory = mock(GhostFactory.class);
        mapParser = new MapParser(levelFactory, boardFactory);
    }
    @Test
    @DisplayName("读取存在的文件")
    public void testParseMap_SunnyDay() throws IOException {
        // 构造一个包含期望字符的map字符串用于测试
        String file = "/map.txt";
        // 构造虚拟的Level对象用于测试
        Level level = mock(Level.class);
        // 模拟LevelFactory.createLevel()返回虚拟的Level对象
        when(levelFactory.createLevel(any(),any(),any())).thenReturn(level);
        // 模拟addSquare()、makeGhostSquare()和makePelletSquare()方法的调用并返回虚拟对象
        when(boardFactory.createGround()).thenReturn(mock(Square.class));
        when(boardFactory.createWall()).thenReturn(mock(Square.class));
        when(levelFactory.createGhost()).thenReturn(mock(Ghost.class));
        when(levelFactory.createPellet()).thenReturn(mock(Pellet.class));
        // 调用MapParser.parseMap()方法读取测试用map字符串
        mapParser.parseMap(file);
        // 验证LevelFactory.createLevel()方法被正确调用
        verify(levelFactory, times(1)).createLevel(any(),any(),any());
        // 验证BoardFactory.createGround()、createWall()方法被正确调用
        verify(boardFactory, times(14)).createGround();//创建可占据格子
        verify(boardFactory, times(21)).createWall();//创建墙
        verify(levelFactory, times(1)).createGhost();//创建鬼
        verify(levelFactory, times(11)).createPellet();//创建豆子

    }
    @Test
    @DisplayName("读取不存在的文件")
    void notExistFile(){
        String file="/NoMap.txt";
        assertThatThrownBy(()->{
            mapParser.parseMap(file);
        }).isInstanceOf(PacmanConfigurationException.class).hasMessage("Could not get resource for: "+file);
    }
    @Test
    @DisplayName("读取文件为null")
    void NameNullFile(){
        String file = null;
        assertThrows(NullPointerException.class, () -> {
            mapParser.parseMap(file);
        });
    }
    @Test
    @DisplayName("读取无法识别的文件")
    void notReadFile(){
        String file="/invalidMap.mat";
        assertThatThrownBy(()->{
            mapParser.parseMap(file);
        }).isInstanceOf(PacmanConfigurationException.class).hasMessage("Could not get resource for: /invalidMap.mat");
    }
    @Test
    @DisplayName("读取的地图文件不是长方形")
    void NoRectangularFile(){
        String file="/map2.txt";
        assertThatThrownBy(()->{
            mapParser.parseMap(file);
        }).isInstanceOf(PacmanConfigurationException.class).hasMessage("Input text lines are not of equal width.");
    }
    @Test
    @DisplayName("读取的地图文件没有内容")
    void NoContentFile(){
        String file="/map3.txt";
        assertThatThrownBy(()->{
            mapParser.parseMap(file);
        }).isInstanceOf(PacmanConfigurationException.class).hasMessage("Input text must consist of at least 1 row.");
    }
    @Test
    @DisplayName("读取的地图文件存在空行")
    void HaveEmptyRowsFile(){
        String file="/map4.txt";
        assertThatThrownBy(()->{
            mapParser.parseMap(file);
        }).isInstanceOf(PacmanConfigurationException.class).hasMessage("Input text lines are not of equal width.");
    }
}
